import { CardUsingEventHandler, CardUsingEventWrapper, EmptyCardUsingEventHandler } from "../playersystem/handlers";
import { PhaseEnum } from "../playersystem/phase";
import { Player } from "../playersystem/player";
import { BasicCard, Color, HurtType, Card, CardProxy, CardWrapper } from "./card"

const DefaultPromise = <T>(t:T) => new Promise<T>((resolve) => resolve(t));

export class Jiu extends BasicCard {

    jiushaProxy: CardProxy<Sha>

    constructor(color: Color, number: number) {
        super(color, number)
        const jiushaProxy: CardProxy<Sha> = {
            name: 'jiushaProxy',
            shouldApply(card: Sha): boolean {
                return card instanceof Sha
            },

            apply(card: Sha): Card {
                const jiushaCard = new JiuSha(card)
                return jiushaCard
            },

            equals(obj: CardProxy<Sha>) {
                return this.name == obj.name
            },

            expirePhase() {
                return PhaseEnum.USING
            }

        }

        class JiuSha extends ShaWrapper {

            createCardUsingEventHandler(card: Sha, player: Player | null): CardUsingEventHandler<Sha> {
                const res = this.sourceCard.createCardUsingEventHandler(card, player)

                class JiuShaEvent extends CardUsingEventWrapper<Sha> {
                    async calHurt(): Promise<number> {
                        const baseHurt = await this.cardUsingEventHandler.calHurt()
                        return DefaultPromise(baseHurt + 1)
                    }
                }

                return new JiuShaEvent(res)
            }

            onDrop(): void {
                // TODO 移除玩家酒 状态
                if (this.cardProperties.owner) {
                    this.cardProperties.owner.handCardAreas.removeCardProxy(jiushaProxy)
                }
                // 回收要处理原牌
                this.sourceCard.onDrop()
            }

            info(): string {
                return "酒" + this.sourceCard.info()
            }
        }
        this.jiushaProxy = jiushaProxy
    }

    info(): string {
        return "酒"
    }

    canuse(): boolean {
        if (this.cardProperties.owner) {
            return !this.cardProperties.owner.handCardAreas.hasCardProxy(this.jiushaProxy)
        }
        return false
    }

    onDrop(): void {
        
        super.onDrop()
    }

    async use(): Promise<void> {
        if (this.cardProperties.owner) {
            this.cardProperties.owner.handCardAreas.registerCardProxy(this.jiushaProxy)
        }

        return super.use()
    }

    async response(source: Card): Promise<Card> {
        if (this.cardProperties.owner) {
            this.cardProperties.owner.recoverHP(1)
        }
        return super.response(source)
    }

    

}

export class Sha extends BasicCard {

    shaHurtType: HurtType

    constructor(color: Color, number: number, shaHurtType?: HurtType) {
        super(color, number)
        if (!shaHurtType) {
            this.shaHurtType = HurtType.NORMAL
        } else {
            this.shaHurtType = shaHurtType
        }
        
    }

    async use(): Promise<void> {
        // 从卡牌创建本身
        let shaEvent = this.createCardUsingEventHandler(this, this.cardProperties.owner)
        if (this.cardProperties.owner) {
            const owner = this.cardProperties.owner
            this.cardProperties.source = owner
            const gm = owner.gameManager
            if (this.cardProperties.source) {
                // 从原对象创建
                shaEvent = this.cardProperties.source.createCardUsingEventHandler(shaEvent)
            }

            // 借刀杀人等场景，如果目标已经被迫指定,不能发起主动指定
            if (!this.cardProperties.target) {
                // 指定目标对象
                await this.waitforSpecTarget(this.cardProperties.source)
            }

            await shaEvent.startCardUse()

            if (this.cardProperties.target) {
                // 从目标对象创建
                shaEvent = this.cardProperties.target.createCardUsingEventHandler(shaEvent)

                owner.handCardAreas.dropCard(this)
                gm.appendDeskCard(this)
                gm.appendLog(`${owner.name} 对目标 ${this.cardProperties.target.name} 使用了 ${this.colorCN()} ${this.numberCN()} ${this.info()},等待目标响应...`)
                await shaEvent.specTarget()
                // 仁王盾等技能可以在specTarget 使得杀变无效
                if (!this.cardProperties.cancelEffect) {
                    // 马超,黄忠等技能可以使得目标无法出闪
                    const respResult = await shaEvent.needAndWaitForResponse(Shan)

                    await shaEvent.afterResponse(respResult.selectedCards, respResult.cancel)
                    // 默认的afterResponse做出一张闪即可使得杀变无效 无双等技能可以在 afterResponse处理再出一张闪才能无效
                    // 贯石斧、青龙偃月刀 在afterResponse 处处理,贯石斧在弃之两张牌后可以使得该杀继续有效,青龙偃月刀 是无效,但可以继续打出新的 card.use()
                    if (!this.cardProperties.cancelEffect) {
                        // 默认杀伤害是1, 酒,古锭刀,火烧藤甲,裸衣,白银狮子等技能情况都可以在此处定义累加伤害
                        const hurtCount = await shaEvent.calHurt()
                        // 默认杀伤害结算就是目标掉血
                        await shaEvent.settleHurt(hurtCount)
                        gm.appendLog(`${this.cardProperties.target.name} 无法出闪,造成 ${hurtCount} 点伤害`)
                        // 濒死状态的处理
                        await shaEvent.playerBeingDead()
                        // 很多技能都可以在受到伤害后释放,造成伤害后释放
                        await shaEvent.afterSettle()

                    }
                }
                // 方天画戟 会在这里处理下一轮目标对象
                await shaEvent.afterUsing()
            }

        }
    }

    canPickPlayer(): boolean {
        if (!this.cardProperties.owner) {
            return false
        }
        const gm = this.cardProperties.owner.gameManager
        const maxdistance = this.specDistance(this.cardProperties.owner)
        const canPickPlayers = gm.distanceN(maxdistance)
        return canPickPlayers.length > 0
    }

    async waitforSpecTarget(source: Player): Promise<void> {
        const gm = source.gameManager
        const maxdistance = this.specDistance(source)
        const canPickPlayers = gm.distanceN(maxdistance)
        const pickNumber = 1
        const options = {canPickPlayers, canPickMin: pickNumber, canPickMax: pickNumber, currentPlayer: source}
        const pickResult = await source.behaviorStragy.waitForPickPlayer(options)
        let targetPlayer = null

        if (pickResult.cancel || pickResult.selectedPlayers.length < 1) {
            targetPlayer = null
        } else {
            targetPlayer = pickResult.selectedPlayers[0]
        }
        // 指定目标对象
        this.cardProperties.target = targetPlayer
    }

    specDistance(player: Player) {
        return player.calAttackDist()
    }

    createCardUsingEventHandler(card: Sha, player: Player | null): CardUsingEventHandler<Sha> {
        class NormalShaEvent extends EmptyCardUsingEventHandler<Sha> {
            calHurt(): Promise<number> {
                return DefaultPromise(1)
            }

            afterResponse(respCard: Card[], cancel: boolean): Promise<void> {
                // 出了闪,没取消
                this.card.cardProperties.cancelEffect = !cancel && respCard.length > 0
                if (this.card.cardProperties.cancelEffect) {
                    const firstRespCard = respCard[0]
                    if (this.player) {
                        const gm = this.player.gameManager
                        if (this.card.cardProperties.target) {
                            gm.appendLog(`${this.card.cardProperties.target.name} 响应一张 ${firstRespCard.colorCN()} ${firstRespCard.numberCN()} 的 ${firstRespCard.info()}`)
                        }
                    }
                    
                }
                return super.afterResponse(respCard, cancel)
            }

            settleHurt(n: number): Promise<void>  {
                if (!this.card.cardProperties.target || !this.card.cardProperties.source || !this.card.cardProperties.owner) {
                    return super.settleHurt(n)
                }
                // 寒冰剑等技能在此处仍可阻止伤害
                if (!this.card.cardProperties.cancelEffect) {
                    this.card.cardProperties.target.reduceHP(n)
                }
                return super.settleHurt(n)
            }

            afterUsing(): Promise<void> {
                const sourceCard = this.card
                if (sourceCard.cardProperties.owner) {
                    const owner = sourceCard.cardProperties.owner
                    const gm = owner.gameManager
                    owner.handCardAreas.dropCard(sourceCard)
                    sourceCard.onDrop()
                    gm.updateView()
                }
                return super.afterUsing()
            }
        }

        return new NormalShaEvent(card, player)
    }

    canuse(): boolean {
        if (!this.cardProperties.owner) {
            return false
        }
        // 默认的杀只能用一次
        return this.cardProperties.owner.handCardAreas.countUsedCard(Sha) < 1 && this.canPickPlayer()
    }

    hurtType(): HurtType {
        return this.shaHurtType
    }

    info(): string {
        switch (this.shaHurtType) {
            case HurtType.THUNDER:
                return "雷杀"
            case HurtType.FIRE:
                return "火杀"
            case HurtType.NORMAL:
                return "杀"
            default:
                return "杀"
        }
    }

}

export class ShaWrapper extends Sha {
    sourceCard: Sha
    constructor(sourceCard: Sha) {
        super(sourceCard.color, sourceCard.number, sourceCard.shaHurtType)
        this.sourceCard = sourceCard
        this.id = sourceCard.id
        this.cardProperties = sourceCard.cardProperties
    }

    onDrop(): void {
        // 回收要处理原牌
        this.sourceCard.onDrop()
    }

    canuse(): boolean {
        return this.sourceCard.canuse()
    }

    getSouceCard(): Card {
        return this.sourceCard.getSouceCard()
    }

}

export class Shan extends BasicCard {

    constructor(color: Color, number: number) {
        super(color, number)
    }

    info(): string {
        return "闪"
    }

    canuse(): boolean {
        return false
    }

    async response(source: Card): Promise<Card> {
        source.cardProperties.cancelEffect = true
        return super.response(source)
    }

}

export class Tao extends BasicCard {

    constructor(color: Color, number: number) {
        super(color, number)
    }

    info(): string {
        return "桃"
    }

    canuse(): boolean {
        if (this.cardProperties.owner) {
            return this.cardProperties.owner.currentHP < this.cardProperties.owner.maxHP
        }
        return false
    }

    async use(): Promise<void> {
        if (this.cardProperties.owner) {
            this.cardProperties.owner.recoverHP(1)
            this.cardProperties.owner.gameManager.appendLog(`${this.cardProperties.owner.name} 使用了一张桃,回复一点体力,当前体力值${this.cardProperties.owner.currentHP}`)
        }
        return super.use()
    }

    async response(source: Card): Promise<Card> {
        if (source.cardProperties.target) {
            source.cardProperties.target.recoverHP(1)
        }
        return super.response(source)
    }

}

